
from app.utils.log_core import LogCore, DeviceLogger, StatusLogger
import inspect
import traceback
import threading

class Log:
    _log_open = False
    lock_1 = None
    lock_2 = None
    def __init__(self, name: int, log_enable = True):
        self.name = name
        self.log_enable = log_enable
        if not Log._log_open:
            Log.Open()
    @staticmethod  
    def get_lock_1():
        if Log.lock_1 is None:
            Log.lock_1 = threading.Lock() 
        return Log.lock_1
    
    @staticmethod
    def get_lock_2():
        if Log.lock_2 is None:
            Log.lock_2 = threading.Lock() 
        return Log.lock_2
    
    @staticmethod
    def Open(enable_console: bool = False) :
        Log._log_open = True
        DeviceLogger.Open(enable_console,keep_file_cnt=50)
        StatusLogger.Open(enable_console,keep_file_cnt=1000)   
        Log.lock_1 = Log.get_lock_1()
        Log.lock_2 = Log.get_lock_2()

    def WARN(self, msg : str):
        DeviceLogger.Warn(f"[{self.name}]" + msg)

    def INFO(self, msg : str):
        if self.log_enable:
            with Log.lock_1:
                DeviceLogger.Info(f"[{self.name}]" + msg)
        
    def DEBUG(self, msg : str):
        if self.log_enable:
            DeviceLogger.Debug(f"[{self.name}]" + msg)
        
    def ERROR(self, msg : str):
        
        # 获取调用该函数的上一层栈帧
        frame = inspect.currentframe().f_back
        # 提取当前帧的信息（文件名、行号等）
        frame_info = inspect.getframeinfo(frame)
        
        # 如果当前调用者是类中的方法，则获取类名
        cls_name = ""
        if "self" in frame.f_locals:
            cls_name = frame.f_locals["self"].__class__.__name__
        
        # 获取调用栈的完整轨迹（从调用处开始的堆栈）
        stack_trace = "".join(traceback.format_stack(frame))
        
        # 构造完整的日志信息，包含名称、类名、文件和行号以及调用栈轨迹
        log_message = (
            f"[{cls_name}] "                       # 类名（如果有）
            f"[{frame_info.filename}:{frame_info.lineno}] "  # 文件名和行号
            f"{msg}\n"
            f"Traceback (most recent call last):\n{stack_trace}"
        )
        with Log.lock_1:
            DeviceLogger.Error(f"[{self.name}] " + log_message)
        with Log.lock_2:
            StatusLogger.Error(f"[{self.name}] " + msg)
        
    def LoggerPause(self):
        DeviceLogger.Pause()
        
    def LoggerResume(self):
        DeviceLogger.Resume()
        
    def StatusInfo(self, msg : str):
        with Log.lock_2:
            StatusLogger.Info(f"[{self.name}]" + msg)
        
    def StatusError(self, msg : str):
        
            # 获取调用该函数的上一层栈帧
        frame = inspect.currentframe().f_back
        # 提取当前帧的信息（文件名、行号等）
        frame_info = inspect.getframeinfo(frame)
        
        # 如果当前调用者是类中的方法，则获取类名
        cls_name = ""
        if "self" in frame.f_locals:
            cls_name = frame.f_locals["self"].__class__.__name__
        
        # 获取调用栈的完整轨迹（从调用处开始的堆栈）
        stack_trace = "".join(traceback.format_stack(frame))
        
        # 构造完整的日志信息，包含名称、类名、文件和行号以及调用栈轨迹
        log_message = (
            f"[{cls_name}] "                       # 类名（如果有）
            f"[{frame_info.filename}:{frame_info.lineno}] "  # 文件名和行号
            f"{msg}\n"
            f"Traceback (most recent call last):\n{stack_trace}"
        )
        with Log.lock_1:
            DeviceLogger.Error(f"[{self.name}]" + log_message)
        with Log.lock_2:
            StatusLogger.Error(f"[{self.name}]" + msg)
        
    @staticmethod
    def _StatusInfo(name, msg : str):
        with Log.lock_2:
            StatusLogger.Info(f"[{name}]" + msg)
        
    @staticmethod
    def _StatusError(name, msg : str):
        
        # 获取调用该函数的上一层栈帧
        frame = inspect.currentframe().f_back
        # 提取当前帧的信息（文件名、行号等）
        frame_info = inspect.getframeinfo(frame)
        
        # 如果当前调用者是类中的方法，则获取类名
        cls_name = ""
        if "self" in frame.f_locals:
            cls_name = frame.f_locals["self"].__class__.__name__
        
        # 获取调用栈的完整轨迹（从调用处开始的堆栈）
        stack_trace = "".join(traceback.format_stack(frame))
        
        # 构造完整的日志信息，包含名称、类名、文件和行号以及调用栈轨迹
        log_message = (
            f"[{cls_name}] "                       # 类名（如果有）
            f"[{frame_info.filename}:{frame_info.lineno}] "  # 文件名和行号
            f"{msg}\n"
            f"Traceback (most recent call last):\n{stack_trace}"
        )
        with Log.lock_1:
            DeviceLogger.Error(f"[{name}] " + log_message)
        with Log.lock_2:
            StatusLogger.Error(f"[{name}] " + msg)
